<template>
  <div class="dashboard-container">
    <!-- 顶部统计卡片 -->
    <el-row :gutter="20" class="mb-4 stats-row" justify="center">
      <!-- 在线设备（第一个卡片，作为样式基准） -->
      <el-col :xs="24" :sm="12" :md="6" :lg="6">
        <el-card class="stats-card bg-gradient-blue">
          <div class="stat-item">
            <!-- 统一添加图标（使用对应语义的图标） -->
            <el-icon class="stat-icon"><Monitor /></el-icon>
            <div class="stat-content">
              <div class="stat-label">在线设备</div>
              <div class="stat-value">{{ stats.online }}</div>
              <div class="stat-trend"><span class="up">↑ 12%</span> 过去24小时</div>
            </div>
          </div>
        </el-card>
      </el-col>

      <!-- 离线设备（补充图标和统一结构） -->
      <el-col :xs="24" :sm="12" :md="6" :lg="6">
        <el-card class="stats-card bg-gradient-green">
          <div class="stat-item">
            <el-icon class="stat-icon"><WarningFilled /></el-icon>
            <!-- 替换为离线对应的图标 -->
            <div class="stat-content">
              <div class="stat-label">离线设备</div>
              <div class="stat-value">{{ stats.offline }}</div>
              <div class="stat-trend"><span class="down">↓ 41%</span> 过去24小时</div>
            </div>
          </div>
        </el-card>
      </el-col>

      <!-- 今日告警（补充图标和统一结构） -->
      <el-col :xs="24" :sm="12" :md="6" :lg="6">
        <el-card class="stats-card bg-gradient-purple">
          <div class="stat-item">
            <el-icon class="stat-icon"><BellFilled /></el-icon>
            <!-- 告警对应铃铛图标 -->
            <div class="stat-content">
              <div class="stat-label">今日告警</div>
              <div class="stat-value">{{ stats.alerts }}</div>
              <div class="stat-trend"><span class="up">↑ 20%</span> 过去24小时</div>
            </div>
          </div>
        </el-card>
      </el-col>

      <!-- 风险设备（补充图标和统一结构） -->
      <el-col :xs="24" :sm="12" :md="6" :lg="6">
        <el-card class="stats-card bg-gradient-orange">
          <div class="stat-item">
            <el-icon class="stat-icon"><Opportunity /></el-icon>
            <!-- 风险对应危险图标，需替换为实际存在的图标 -->
            <div class="stat-content">
              <div class="stat-label">风险设备</div>
              <div class="stat-value">{{ stats.risky }}</div>
              <div class="stat-trend"><span class="down">↓ 14%</span> 过去24小时</div>
            </div>
          </div>
        </el-card>
      </el-col>
    </el-row>

    <!-- 主内容区 -->
    <el-row :gutter="20">
      <!-- 右侧设备列表 -->
      <el-col :span="24">
        <el-card class="device-card">
          <template #header>
            <div class="card-header">
              <span>物联网设备状态</span>
              <el-button type="primary" size="small" @click="fetchDevices">刷新</el-button>
            </div>
          </template>
          <!-- 将过滤器内容移到设备卡片内部 -->
          <div class="filter-section">
            <el-space :size="20">
              <el-input
                v-model="searchKeyword"
                placeholder="设备名称/IP搜索"
                prefix-icon="Search"
                clearable
              />
              <el-select v-model="eventType" size="small" @change="handleEventChange">
                <el-option
                  v-for="item in eventTypes"
                  :key="item.value"
                  :label="item.label"
                  :value="item.value"
                />
              </el-select>
              <el-date-picker
                v-model="timeRange"
                type="datetimerange"
                range-separator="-"
                start-placeholder="开始时间"
                end-placeholder="结束时间"
              />
              <el-button type="primary" size="small" @click="handleFilterChange">搜索</el-button>
            </el-space>
          </div>
          <el-table :data="devices" style="width: 100%" :row-class-name="deviceRowClassName">
            <el-table-column prop="name" label="设备名称"></el-table-column>
            <el-table-column prop="ip" label="IP地址"></el-table-column>
            <el-table-column label="状态">
              <template #default="{ row }">
                <el-tag :type="row.status === '在线' ? 'success' : 'danger'" size="small">
                  {{ row.status }}
                </el-tag>
              </template>
            </el-table-column>
            <el-table-column label="操作">
              <template #default="{ row }">
                <el-button
                  type="primary"
                  size="small"
                  link
                  :icon="Right"
                  class="detail-btn"
                  @click="showDeviceDetail(row.id)"
                >
                  查看详情
                </el-button>
              </template>
            </el-table-column>
          </el-table>
        </el-card>
      </el-col>
    </el-row>
    <el-row :gutter="20" class="mt-4">
      <el-col :span="10">
        <el-card class="analysis-card">
          <template #header>
            <div class="card-header">
              <span>威胁类型分析</span>
              <el-tooltip content="基于最近30天数据">
                <el-icon><InfoFilled /></el-icon>
              </el-tooltip>
            </div>
          </template>
          <div ref="threatChart" class="mini-chart"></div>
          <el-table :data="threatData" size="small">
            <el-table-column prop="type" label="攻击类型" />
            <el-table-column prop="count" label="次数" />
            <el-table-column label="趋势">
              <template #default="{ row }">
                <span :class="row.trend > 0 ? 'up' : 'down'">
                  {{ row.trend > 0 ? '+' : '' }}{{ row.trend }}%
                </span>
              </template>
            </el-table-column>
          </el-table>
        </el-card>
      </el-col>
      <el-col :span="14">
        <el-card class="notification-card">
          <template #header>
            <div class="card-header">
              <el-space :size="20">
                <span>实时安全通知</span>
                <el-badge :value="notifications.length" />
              </el-space>
              <el-switch
                v-model="realTimeAlert"
                active-text="开启实时推送"
                inactive-text="关闭通知"
              />
            </div>
          </template>
          <el-scrollbar>
            <div
              v-for="(item, index) in notifications"
              :key="index"
              class="alert-item"
              @click="showNotificationDetail(item.id)"
            >
              <div class="alert-left">
                <el-icon
                  :class="item.type"
                  :color="item.type === 'critical' ? '#ff4d4f' : '#faad14'"
                >
                  <component :is="item.type === 'critical' ? 'WarningFilled' : 'BellFilled'" />
                </el-icon>
                <div class="alert-level">{{ item.type === 'critical' ? '紧急' : '警告' }}</div>
              </div>
              <div class="alert-main">
                <div class="alert-header">
                  <div class="alert-title">{{ item.title }}</div>
                  <div class="alert-time">{{ item.time }}</div>
                </div>
                <div class="alert-actions">
                  <el-button type="primary" size="small" link :icon="Right" class="detail-btn">
                    查看详情
                  </el-button>
                  <el-tag size="small" :type="item.type === 'critical' ? 'danger' : 'warning'">
                    {{ item.type.toUpperCase() }}
                  </el-tag>
                </div>
              </div>
            </div>
          </el-scrollbar>
        </el-card>
      </el-col>
    </el-row>
    <el-row :gutter="20" class="mt-4">
      <el-col :span="24">
        <el-card class="visualization-card">
          <template #header>
            <div class="card-header">
              <el-space :size="20">
                <span>安全态势感知</span>
                <el-select v-model="chartType" size="small">
                  <el-option label="实时风险" value="gauge" />
                  <el-option label="历史趋势" value="line" />
                </el-select>
              </el-space>
              <el-space>
                <el-date-picker
                  v-model="timeRange"
                  type="datetimerange"
                  range-separator="-"
                  start-placeholder="开始时间"
                  end-placeholder="结束时间"
                  size="small"
                />
                <el-tag type="danger">实时流数据</el-tag>
              </el-space>
            </div>
          </template>
          <div ref="riskChart" class="chart-container"></div>
        </el-card>
      </el-col>
    </el-row>

    <!-- 新增攻击统计面板 -->
    <el-card class="mt-4 attack-stats">
      <template #header>
        <div class="card-header">
          <span>最近安全事件</span>
          <el-link type="primary" :underline="false" @click="showAllEvents">查看全部</el-link>
        </div>
      </template>
      <el-timeline>
        <el-timeline-item v-for="(event, index) in securityEvents.slice(0, 3)" :key="index">
          <el-alert :title="event.description" :type="event.level" :closable="false" show-icon />
        </el-timeline-item>
      </el-timeline>
    </el-card>
  </div>
</template>
<script setup lang="ts">
import { ref, onMounted, watch } from 'vue'
import * as echarts from 'echarts'
import axios from 'axios'
import { ElMessage } from 'element-plus'
import { useRouter } from 'vue-router'
import { io } from 'socket.io-client'
import { Monitor, WarningFilled, BellFilled, Opportunity, Right } from '@element-plus/icons-vue'

interface Device {
  id: number
  name: string
  ip: string
  status: string
}

interface SecurityEvent {
  time: string
  description: string
  level: 'success' | 'warning' | 'info' | 'error'
}

// 新增数据响应
const eventType = ref('all')
interface EventType {
  value: string
  label: string
}
const eventTypes = ref<EventType[]>([])

// 获取事件类型
const fetchEventTypes = async () => {
  const res = await axios.get('http://127.0.0.1:5000/api/event-types')
  eventTypes.value = res.data.data
}

// 处理事件类型变化
const handleEventChange = () => {
  fetchRiskHistory()
}

// 数据响应
const devices = ref<Device[]>([])
const riskScore = ref(0)
const riskChart = ref<HTMLElement | null>(null)
const myChart = ref<echarts.ECharts | null>(null)
const stats = ref({
  online: 0,
  offline: 0,
  alerts: 0,
  risky: 0,
})

const securityEvents = ref<SecurityEvent[]>([
  {
    time: '2023-09-20 14:30',
    description: '智能门锁异常登录尝试',
    level: 'error',
  },
  {
    time: '2023-09-20 13:45',
    description: '摄像头流量异常波动',
    level: 'warning',
  },
])

// 图表类型切换
const chartType = ref('gauge')

// 时间范围选择
const timeRange = ref<[Date, Date]>()

// 威胁分析数据
interface ThreatData {
  type: string
  count: number
  trend: number
}
const threatData = ref<ThreatData[]>([])

// 实时通知数据
interface Notification {
  id: number
  title: string
  time: string
  type: 'critical' | 'warning'
}
const notifications = ref<Notification[]>([
  { id: 1, title: '检测到异常流量', time: '14:30', type: 'critical' },
  { id: 2, title: '设备离线警告', time: '14:25', type: 'warning' },
])

// 实时警报开关
const realTimeAlert = ref(true)

// 过滤条件
const searchKeyword = ref('')
const deviceStatus = ref<string[]>([])
const riskLevel = ref<string>()

// 设备表格行样式
const deviceRowClassName = ({ row }: { row: Device }) => {
  return row.status === '离线' ? 'warning-row' : ''
}

// 获取设备列表
const fetchDevices = async () => {
  const params = {
    status: deviceStatus.value,
    risk_level: riskLevel.value,
    start: timeRange.value?.[0].toISOString(),
    end: timeRange.value?.[1].toISOString(),
    keyword: searchKeyword.value,
  }

  const res = await axios.get('http://127.0.0.1:5000/api/devices', { params })
  devices.value = res.data.data
}

const fetchSecurityEvents = async () => {
  try {
    const res = await axios.get('http://127.0.0.1:5000/api/security-events')
    securityEvents.value = res.data.data
  } catch (error) {
    console.error('获取安全事件失败:', error)
  }
}

const fetchNotifications = async () => {
  try {
    const res = await axios.get('http://127.0.0.1:5000/api/notifications')
    notifications.value = res.data.data
  } catch (error) {
    console.error('获取通知失败:', error)
  }
}

// 更新统计信息
const updateStats = async () => {
  try {
    const res = await axios.get('http://127.0.0.1:5000/api/stats')
    stats.value = res.data.data
  } catch (error) {
    console.error('获取统计信息失败:', error)
  }
}

// 获取风险评分
const fetchRiskScore = async () => {
  try {
    const requestData = {
      features: [
        [1, 2, 3, 4, 5],
        [6, 7, 8, 9, 10],
        [11, 12, 13, 14, 15],
        [16, 17, 18, 19, 20],
        [21, 22, 23, 24, 25],
        [26, 27, 28, 29, 30],
        [31, 32, 33, 34, 35],
        [36, 37, 38, 39, 40],
        [41, 42, 43, 44, 45],
        [46, 47, 48, 49, 50],
      ],
    }
    const res = await axios.post('http://127.0.0.1:5000/api/risk', requestData, {
      headers: {
        'Content-Type': 'application/json',
      },
    })
    riskScore.value = res.data.data
    updateChart()
  } catch (error) {
    console.error('获取风险评分失败:', error)
  }
}

// 获取威胁分析数据
const fetchThreatAnalysis = async () => {
  try {
    const res = await axios.get('http://127.0.0.1:5000/api/threat-analysis')
    // 处理数据格式
    threatData.value = res.data.data.types
  } catch (error) {
    console.error('获取威胁分析数据失败:', error)
  }
}

// 新增历史数据响应
const riskHistory = ref<{ time: string; score: number }[]>([])

// 获取历史风险数据
const fetchRiskHistory = async () => {
  try {
    const params = {
      start: timeRange.value?.[0]?.toISOString(),
      end: timeRange.value?.[1]?.toISOString(),
    }

    const res = await axios.get('http://127.0.0.1:5000/api/risk-history', { params })
    riskHistory.value = res.data.data
    updateChart()
  } catch (error) {
    console.error('获取历史数据失败:', error)
  }
}

const showNotificationDetail = (notificationId: number) => {
  router.push(`/notifications/${notificationId}`)
}

// 修改图表生成逻辑
const getEChartsOption = (value: number) => {
  if (chartType.value === 'gauge') {
    return {
      series: [
        {
          type: 'gauge',
          axisLine: {
            lineStyle: {
              color: [
                [0.2, '#91c7ae'],
                [0.8, '#63869e'],
                [1, '#c23531'],
              ],
              width: 8,
            },
          },
          pointer: {
            itemStyle: {
              color: 'auto',
            },
          },
          axisTick: {
            splitNumber: 10,
            lineStyle: {
              color: '#fff',
              width: 2,
            },
          },
          splitLine: {
            length: 15,
            lineStyle: {
              color: '#fff',
            },
          },
          axisLabel: {
            color: 'auto',
          },
          title: {
            textStyle: {
              fontWeight: 'bolder',
              fontSize: 20,
              color: '#333',
            },
          },
          detail: {
            formatter: '{value}%',
            textStyle: {
              color: 'auto',
              fontWeight: 'bolder',
              fontSize: 30,
            },
          },
          data: [
            {
              value,
              name: '风险评分',
            },
          ],
        },
      ],
    }
  } else {
    return {
      xAxis: {
        type: 'category',
        data: riskHistory.value.map((item) => item.time),
      },
      yAxis: { type: 'value' },
      series: [
        {
          type: 'line',
          data: riskHistory.value.map((item) => item.score),
          areaStyle: {},
          smooth: true,
        },
      ],
    }
  }
}

// 监听图表类型变化
watch(chartType, () => {
  if (chartType.value === 'line') fetchRiskHistory()
})

// 初始化 ECharts 仪表盘
const initECharts = () => {
  if (riskChart.value) {
    myChart.value = echarts.init(riskChart.value)
    const option = getEChartsOption(riskScore.value)
    myChart.value.setOption(option)
  }
}

// 更新 ECharts 图表的方法
const updateChart = () => {
  if (myChart.value) {
    const option = getEChartsOption(riskScore.value)
    myChart.value.setOption(option)
  }
}

// 过滤器变化处理
const handleFilterChange = () => {
  fetchDevices()
  fetchThreatAnalysis()
}

// 设备详情跳转
const router = useRouter()

const showDeviceDetail = (deviceId: number) => {
  router.push(`/devices/${deviceId}`)
}

let socket: any = null

const setupWebSocket = () => {
  if (realTimeAlert.value) {
    socket = io('http://localhost:5000')
    socket.on('notification', (data: Notification) => {
      notifications.value.unshift(data)
    })
  } else {
    socket?.disconnect()
  }
}

// 监听开关状态变化
watch(realTimeAlert, (newVal) => {
  if (newVal) setupWebSocket()
  else socket?.disconnect()
})

const showAllEvents = () => {
  router.push('/security-events')
}

// 组件挂载后执行的操作
onMounted(async () => {
  await fetchDevices()
  await updateStats()
  await fetchThreatAnalysis()
  await fetchSecurityEvents()
  await fetchNotifications()
  setupWebSocket()
  initECharts()
  const intervalId = setInterval(fetchRiskScore, 5000)
  return () => clearInterval(intervalId)
})
</script>
<style>
/* 基础布局 */
.dashboard-container {
  padding: 30px;
  width: 100%; /* 新增 */
  margin: auto auto;
  background-color: #f5f7fa;
  box-sizing: border-box; /* 新增 */
  min-width: 1200px;
}

/* 优化卡片间距 */
.el-row {
  margin-bottom: 20px;
}

/* 图表容器增加响应式 */
.chart-container {
  height: 800px; /* 增加高度 */
}

.stats-row {
  margin: 0 -10px;
}
.stats-card {
  border-radius: 12px;
  margin: 10px;
  transition: transform 0.3s;
}
.stats-card:hover {
  transform: translateY(-5px);
}
.stat-item {
  display: flex;
  align-items: center;
  padding: 20px;
}
.stat-icon {
  font-size: 40px;
  margin-right: 20px;
  opacity: 0.8;
}
.stat-content {
  flex: 1;
}
.stat-value {
  font-size: 32px;
  margin: 8px 0;
}
.stat-trend {
  font-size: 12px;
  color: rgba(255, 255, 255, 0.8);
}
.up {
  color: #52c41a;
}
.down {
  color: #ff4d4f;
}

/* 渐变背景 */
.bg-gradient-blue {
  background: linear-gradient(45deg, #409eff, #337ecc);
}
.bg-gradient-green {
  background: linear-gradient(45deg, #67c23a, #529b2e);
}
.bg-gradient-purple {
  background: linear-gradient(45deg, #a460f8, #7d3cc4);
}
.bg-gradient-orange {
  background: linear-gradient(45deg, #e6a23c, #b88230);
}

/* 卡片样式 */
.visualization-card,
.device-card,
.attack-stats {
  border-radius: 8px;
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
}

.card-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-weight: bold;
}

/* 增加模块间距 */
.el-card {
  margin-bottom: 20px;
}

/* 调整图表容器高度 */
.chart-container {
  height: 600px;
}

/* 安全事件时间线 */
.attack-stats .el-timeline {
  padding-left: 20px;
}

.filter-section {
  padding: 10px;
  border-bottom: 1px solid #e4e7ed; /* 添加底部边框，区分过滤器和表格 */
  margin-bottom: 10px;
}

/* 增加卡片内边距 */
.el-card__body {
  padding: 20px;
}

/* 优化通知图标颜色 */
.el-icon[style*='#ff4d4f'] {
  animation: pulse 1.5s infinite;
}

@keyframes pulse {
  0% {
    opacity: 1;
  }
  50% {
    opacity: 0.5;
  }
  100% {
    opacity: 1;
  }
}

/* 响应式布局 */
@media (max-width: 1200px) {
  .el-col {
    width: 100%;
  }

  .chart-container {
    min-width: auto;
    height: 400px;
  }
}

/* 新增通知样式 */
.alert-item {
  display: flex;
  align-items: center;
  padding: 12px 16px;
  margin: 8px 0;
  background: #ffffff;
  border-radius: 8px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
  transition: transform 0.2s;
}

.alert-item:hover {
  transform: translateX(5px);
}

.alert-left {
  display: flex;
  flex-direction: column;
  align-items: center;
  margin-right: 16px;
  min-width: 60px;
}

.alert-level {
  font-size: 12px;
  color: #666;
  margin-top: 4px;
}

.alert-main {
  flex: 1;
}

.alert-header {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
}

.alert-title {
  font-weight: 500;
  color: #303133;
}

.alert-time {
  font-size: 12px;
  color: #909399;
}

.alert-actions {
  margin-top: 8px;
  display: flex;
  gap: 8px;
  align-items: center;
}

.detail-btn {
  transition: all 0.3s;
  padding: 4px 8px !important;
}

.detail-btn:hover {
  color: #409eff !important;
  transform: translateX(3px);
}

.detail-btn i {
  margin-left: 4px;
  font-size: 12px;
}

/* 统一按钮边距 */
.el-button {
  margin: 0 4px;
}

/* 优化卡片标题间距 */
.card-header {
  padding: 16px 20px;
}

/* 添加过渡动画 */
.chart-container {
  transition: all 0.3s ease;
}

/* 时间线项悬停效果 */
.el-timeline-item:hover {
  transform: translateX(5px);
}
</style>
